﻿using HandyWpf.Utils;
using Microsoft.Xaml.Behaviors;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;

namespace HandyWpf.Behaviors
{
    public class ListViewDragBehavior:Behavior<ListView>
    {
        private object _draggedItem;
        private Point _dragStartPoint;
        private DragDropPreview _draggedItemPreview;

        protected override void OnAttached()
        {
            AssociatedObject.PreviewMouseLeftButtonDown += OnMouseDown;
            AssociatedObject.PreviewMouseMove += OnMouseMove;
            AssociatedObject.Drop += OnDrop;
            //AssociatedObject.DragOver += OnDragOver;
            
        }

        private void OnMouseDown(object sender, MouseButtonEventArgs e)
        {
            _dragStartPoint = e.GetPosition(null);
            _draggedItem = ElementHelper.FindAncestor<ListViewItem>((DependencyObject)e.OriginalSource)?.DataContext;
        }

        private void OnMouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton != MouseButtonState.Pressed || _draggedItem == null) return;

            var currentPos = e.GetPosition(null);
            if ((currentPos - _dragStartPoint).LengthSquared < 100) return;
            //CreatePopupWithControl(_draggedItem);
            DragDrop.DoDragDrop(AssociatedObject, _draggedItem, DragDropEffects.Move);
        }
        private void OnDragOver(object sender, DragEventArgs e)
        {
            if (_draggedItemPreview != null && !_draggedItemPreview.IsOpen)
                _draggedItemPreview.IsOpen = true;

            _draggedItemPreview.Move(e.GetPosition(AssociatedObject));
        }

        private void OnDrop(object sender, DragEventArgs e)
        {
            var targetItem = ElementHelper.FindAncestor<ListViewItem>((DependencyObject)e.OriginalSource)?.DataContext;
            var items = AssociatedObject.ItemsSource as IList;
            if (items == null || _draggedItem == targetItem) return;

            int oldIndex = items.IndexOf(_draggedItem);
            int newIndex = items.IndexOf(targetItem);
            items.RemoveAt(oldIndex);
            items.Insert(newIndex, _draggedItem);
        }

        private void CreatePopupWithControl(object data)
        {
            var newListItem = new ListViewItem();
            newListItem.Content = data;
            newListItem.Style = AssociatedObject.ItemContainerStyle;
            newListItem.ContentTemplate = AssociatedObject.ItemTemplate;

            _draggedItemPreview = new DragDropPreview();
            _draggedItemPreview.PlacementTarget = AssociatedObject;
            _draggedItemPreview.Child = newListItem;
    }

        public class DragDropPreview : Popup
        {
            public DragDropPreview()
            {
                this.AllowsTransparency = true;
                this.AllowDrop = false;
                this.IsHitTestVisible = false;
                this.Focusable = false;
                this.Placement = PlacementMode.Relative;
                this.StaysOpen = true;
                this.HorizontalAlignment = HorizontalAlignment.Left;
                this.VerticalAlignment = VerticalAlignment.Top;
            }
            public Point Translation { get; }

            public Point AnchorPoint { get; }

            public void Move(Point point)
            {
                var translation = this.Translation;
                var translationX = point.X + translation.X;
                var translationY = point.Y + translation.Y;

                if (this.Child is not null)
                {
                    var renderSize = this.Child.RenderSize;

                    var renderSizeWidth = renderSize.Width;
                    var renderSizeHeight = renderSize.Height;


                    if (renderSizeWidth > 0 && renderSizeHeight > 0)
                    {
                        var offsetX = renderSizeWidth * -this.AnchorPoint.X;
                        var offsetY = renderSizeHeight * -this.AnchorPoint.Y;

                        translationX += offsetX;
                        translationY += offsetY;
                    }
                }

                this.SetCurrentValue(HorizontalOffsetProperty, translationX);
                this.SetCurrentValue(VerticalOffsetProperty, translationY);
            }
        }
    }
}
